
use std::arch::asm;

//
fn f1() {
let x: u64;
unsafe {
    asm!("mov {}, 5", out(reg) x);
}
assert_eq!(x, 5);
}

//
fn f2() {
let i: u64 = 3;
let o: u64;
unsafe {
    asm!(
        "mov {0}, {1}",
        "add {0}, 5",
        out(reg) o,
        in(reg) i,
    );
}
assert_eq!(o, 8);
}

//
fn f3() {
let mut k: u64 = 3;
unsafe {
    asm!("add {0}, 5", inout(reg) k);
}
assert_eq!(k, 8);
}

// 
fn f4() {
    let mut k: u64 = 3;
    let t: u64;
    unsafe {
        asm!("add {0}, 5", inout(reg) k => t);
    }
    assert_eq!(t, 8);
}

//
fn f5() {
let mut a: u64 = 4;
let b: u64 = 4;
let c: u64 = 4;
unsafe {
    asm!(
        "add {0}, {1}",
        "add {0}, {2}",
        inout(reg) a,
        in(reg) b,
        in(reg) c,
    );
}
assert_eq!(a, 12);
}

// 
fn mul(a: u64, b: u64) -> u128 {
    let lo: u64;
    let hi: u64;

    unsafe {
        asm!(
            // The x86 mul instruction takes rax as an implicit input and writes
            // the 128-bit result of the multiplication to rax:rdx.
            "mul {}",
            in(reg) a,
            inlateout("rax") b => lo,
            lateout("rdx") hi
        );
    }

    ((hi as u128) << 64) + lo as u128
}

fn main() {
    assert_eq!(mul(3,4), 11);
}


